#ifndef xpack_utils_assign_wrapper
#define xpack_utils_assign_wrapper
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::utils_assign_wrapper::inc
#include"define/base_type.hpp"
#include"macro/xcstyle.hpp"
#include"macro/xexport.hpp"
#include"macro/xis_nullptr.hpp"
#include"macro/xmodify.hpp"
#include"macro/xstruct.hpp"
#include"meta/is_left_ref.hpp"
#include"meta/is_const.hpp"
#include"meta/remove_ref.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_assign_wrapper{
    using assign_invoke = void(*)(void * des, void * src);

    xstruct(
        xname(assign_wrapper),
        xprif(m_ptr, voidp),
        xprif(m_assign, assign_invoke)
    )
        assign_wrapper(decltype(nullptr)) : m_ptr{}, m_assign{}{}

        template<class value_t, class origin_t = inc::remove_ref<value_t>>
        assign_wrapper(value_t && value) :
            m_ptr(xmodify((origin_t &)value)), m_assign(assign_invoke(
                xcstyle(origin_t * des, origin_t * src){
                    // 现判断是否是常量值
                    if constexpr (inc::is_const<value_t &&>){
                        *des    = *(origin_t const *)(src);
                    }
                    // 再判断是否是左值引用
                    else if constexpr (inc::is_left_ref<value_t &&>){
                        *des    = (value_t &&)(*src);
                    }
                    // 最后判断是否是右值引用 is_right_ref
                    else{
                        *des    = *src;
                    }
                }
            )){
        }

        template<class value_t>
        requires(inc::is_const<value_t> == false)
        bstate_t assign_to(value_t * value){
            if (m_ptr == nullptr or value == nullptr){
                return bstate_t::fail;
            }
            else{
                m_assign(value/*des*/, m_ptr/*src*/);
                return bstate_t::success;
            }
        }

        template<class value_t>
        requires(inc::is_const<value_t> == false)
        void assign_to_unsafe(value_t * value){
            m_assign(value/*des*/, m_ptr/*src*/);
        }

        xis_nullptr(
            m_ptr == nullptr
        )
    $
}

#endif

xexport(mixc::utils_assign_wrapper::assign_wrapper)
